#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
RunAllSide-Channel AttackExample
"""

import os
import sys
import time
import subprocess
from pathlib import Path

# Add父DirectoryToPath
sys.path.insert(0, str(Path(__file__).parent.parent))


def check_test_data():
    """CheckTestDataYesNo存In"""
    test_data_dir = Path(__file__).parent.parent / "power_traces"
    required_files = [
        test_data_dir / "aes_test_traces.npz",
        test_data_dir / "sm4_test_traces.npz"
    ]
    
    missing_files = []
    for file_path in required_files:
        if not file_path.exists():
            missing_files.append(file_path)
    
    if missing_files:
        print("[FAIL] 缺少TestDataFile:")
        for file_path in missing_files:
            print(f"   {file_path}")
        print("\n请Run以下CommandGenerateTestData:")
        print("cd /home/ga4ss/workspace/j0ker/xchip")
        print("python3 tools/power_trace_generator.py -a aes -n 50 -o side_channel_attacks/power_traces/aes_test_traces.npz --noise")
        print("python3 tools/power_trace_generator.py -a sm4 -n 30 -o side_channel_attacks/power_traces/sm4_test_traces.npz --noise")
        return False
    
    print("[OK] AllTestDataFile存In")
    return True


def run_example(example_file, description):
    """RunSingleExample"""
    print(f"\n{'='*60}")
    print(f"RunExample: {description}")
    print(f"File: {example_file}")
    print(f"{'='*60}")
    
    try:
        start_time = time.time()
        
        # RunExample
        result = subprocess.run(
            [sys.executable, str(example_file)],
            cwd=example_file.parent,
            capture_output=True,
            text=True,
            timeout=300  # 5分钟超时
        )
        
        end_time = time.time()
        
        print(f"Run时间: {end_time - start_time:.2f}秒")
        print(f"Return码: {result.returncode}")
        
        if result.stdout:
            print(f"\nOutput:")
            print(result.stdout)
        
        if result.stderr:
            print(f"\nErrorOutput:")
            print(result.stderr)
        
        if result.returncode == 0:
            print(f"[OK] {description} RunSuccess")
            return True
        else:
            print(f"[FAIL] {description} RunFailed (Return码: {result.returncode})")
            return False
            
    except subprocess.TimeoutExpired:
        print(f"[Timeout] {description} Run超时")
        return False
    except Exception as e:
        print(f"[FAIL] {description} Run异常: {e}")
        return False


def run_direct_example(example_module, description):
    """直接RunExampleModule"""
    print(f"\n{'='*60}")
    print(f"RunExample: {description}")
    print(f"{'='*60}")
    
    try:
        start_time = time.time()
        
        # 直接导入并Run
        if example_module == "basic_attack_example":
            from examples.basic_attack_example import (
                run_basic_attack_example,
                demonstrate_attack_parameters,
                compare_attack_methods
            )
            run_basic_attack_example()
            demonstrate_attack_parameters()
            compare_attack_methods()
            
        elif example_module == "algorithm_specific_example":
            from examples.algorithm_specific_example import (
                run_aes_specific_attack,
                run_sm4_specific_attack,
                compare_algorithm_attacks,
                demonstrate_leakage_models,
                show_available_algorithms
            )
            show_available_algorithms()
            run_aes_specific_attack()
            run_sm4_specific_attack()
            compare_algorithm_attacks()
            demonstrate_leakage_models()
            
        elif example_module == "attack_manager_example":
            from examples.attack_manager_example import (
                basic_manager_usage,
                run_individual_attacks,
                run_comprehensive_attack,
                demonstrate_manager_features,
                test_different_algorithms,
                configuration_example
            )
            manager = basic_manager_usage()
            if manager:
                run_individual_attacks(manager)
                run_comprehensive_attack(manager)
                demonstrate_manager_features(manager)
                test_different_algorithms()
                configuration_example()
        
        end_time = time.time()
        print(f"\n[OK] {description} RunSuccess (用时: {end_time - start_time:.2f}秒)")
        return True
        
    except Exception as e:
        print(f"[FAIL] {description} RunFailed: {e}")
        import traceback
        traceback.print_exc()
        return False


def main():
    """主Function"""
    print("Side-Channel Attack框架 - Example程序集合")
    print("="*60)
    
    # CheckTestData
    if not check_test_data():
        return 1
    
    # 定义ExampleList
    examples = [
        {
            'module': 'basic_attack_example',
            'description': '基础Side-Channel AttackExample',
            'file': Path(__file__).parent / 'basic_attack_example.py'
        },
        {
            'module': 'algorithm_specific_example',
            'description': 'Algorithm特定AttackExample',
            'file': Path(__file__).parent / 'algorithm_specific_example.py'
        },
        {
            'module': 'attack_manager_example',
            'description': 'Attack管理器UseExample',
            'file': Path(__file__).parent / 'attack_manager_example.py'
        }
    ]
    
    # RunAllExample
    successful_examples = 0
    total_start_time = time.time()
    
    for example in examples:
        # Use直接导入方式Run，Avoidsubprocess的复杂性
        success = run_direct_example(example['module'], example['description'])
        if success:
            successful_examples += 1
    
    total_end_time = time.time()
    
    # Output总体Result
    print(f"\n{'='*60}")
    print("ExampleRun总结")
    print(f"{'='*60}")
    
    print(f"总Run时间: {total_end_time - total_start_time:.2f}秒")
    print(f"SuccessExample: {successful_examples}/{len(examples)}")
    print(f"Success率: {successful_examples/len(examples)*100:.1f}%")
    
    if successful_examples == len(examples):
        print(f"\n[Success] AllExampleRunSuccess!")
        return 0
    else:
        print(f"\n[WARNING] PartialExampleRunFailed")
        return 1


def generate_test_data():
    """GenerateTestData"""
    print("[Tool] GenerateTestData")
    print("-" * 40)
    
    commands = [
        [
            "python3", "tools/power_trace_generator.py",
            "-a", "aes", "-n", "50",
            "-o", "side_channel_attacks/power_traces/aes_test_traces.npz",
            "--noise"
        ],
        [
            "python3", "tools/power_trace_generator.py", 
            "-a", "sm4", "-n", "30",
            "-o", "side_channel_attacks/power_traces/sm4_test_traces.npz",
            "--noise"
        ]
    ]
    
    xchip_dir = Path(__file__).parent.parent.parent
    
    for i, cmd in enumerate(commands, 1):
        print(f"GenerateData {i}/{len(commands)}: {' '.join(cmd)}")
        try:
            result = subprocess.run(
                cmd,
                cwd=xchip_dir,
                capture_output=True,
                text=True,
                timeout=60
            )
            
            if result.returncode == 0:
                print(f"[OK] DataGenerateSuccess")
            else:
                print(f"[FAIL] DataGenerateFailed: {result.stderr}")
                return False
                
        except Exception as e:
            print(f"[FAIL] DataGenerate异常: {e}")
            return False
    
    return True


if __name__ == '__main__':
    try:
        # CheckYesNoRequireGenerateTestData
        if not check_test_data():
            print("\n[Tool] Try自动GenerateTestData...")
            if generate_test_data():
                print("[OK] TestDataGenerateCompleted")
            else:
                print("[FAIL] TestDataGenerateFailed")
                sys.exit(1)
        
        # RunExample
        exit_code = main()
        sys.exit(exit_code)
        
    except KeyboardInterrupt:
        print("\n[WARNING] ExampleRun被用户Interrupt")
        sys.exit(1)
    except Exception as e:
        print(f"\n[FAIL] ExampleRunFailed: {e}")
        sys.exit(1)
